package sk.fei.vrml.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLCapabilities;

import com.sun.opengl.util.Animator;



//import javax.media.opengl.Animator;
//import javax.media.opengl.GLCanvas;
//import javax.media.opengl.GLCanvas;
//import javax.media.opengl.GLCapabilities;
//import javax.media.opengl.GLAutoDrawableFactory;
import sk.fei.vrml.jogl.JoglEventListener;
import sk.fei.vrml.jogl.VrmlModel;
import sk.fei.vrml.main.Constants;
import sk.fei.vrml.main.Main;
import sk.fei.vrml.main.Transformator;
import sk.fei.vrml.objects.VrmlAppearance;
import sk.fei.vrml.objects.VrmlBackground;
import sk.fei.vrml.objects.VrmlBox;
import sk.fei.vrml.objects.VrmlCone;
import sk.fei.vrml.objects.VrmlCylinder;
import sk.fei.vrml.objects.VrmlObject;
import sk.fei.vrml.objects.VrmlShape;
import sk.fei.vrml.objects.VrmlSphere;
import sk.fei.vrml.objects.VrmlText;
import sk.fei.vrml.objects.VrmlTransform;
import sk.fei.vrml.objects.VrmlViewPoint;
import sk.fei.vrml.objects.VrmlViewPointsStorage;
import cv97.field.SFNode;

public class MainFrame extends JFrame{
	private GLCanvas canvas;
	private Animator anim; // animator pre spustanie vykreslovania opengl
	public JoglEventListener listener;
	public VrmlViewPointsStorage viewpointStorage;
	private int cursorType = 0;
	private JTree modelTree;
	private JPanel propertiesPanel,contentPanel;
	private JPopupMenu treePopupMenu;
	private boolean addToHierarchy = false;
	private DefaultMutableTreeNode hierarchyNode;
	private VrmlTransform hierarchyParent;
	private int ViewPointnumber=1;
	private MainFrame _window;
	
	public MainFrame(){
		super("VLRM Editor");
		this.viewpointStorage=new VrmlViewPointsStorage();
		this.setPreferredSize(new Dimension(1200,660));
		this.setMinimumSize(new Dimension(1100,500));
		this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		this.setLayout(new GridBagLayout());
		WindowListener windowListener = new WindowAdapter()
		   {
		   public void windowClosing ( WindowEvent w )
		      {
			   if (listener.getActivModel().wasModelChanged()){
				   int option = JOptionPane.showConfirmDialog(contentPanel, "There are unsaved changes in model do you wish to save changes?");
				   if (option == JOptionPane.CANCEL_OPTION) return;
				   else if (option == JOptionPane.YES_OPTION){
					   listener.getActivModel().getIoobject().exportToFile();
				   }
				   else if (option == JOptionPane.NO_OPTION){
					   exitWindow();
					   return;
				   }
			   }
			   exitWindow();
		      } 
		   };
		this.addWindowListener( windowListener );
			
		
		GridBagConstraints con = new GridBagConstraints();
		con.gridx = 0;
		con.gridy = 0;
		con.gridwidth = 4;
		con.weightx = 0;
		con.weighty = 0;
		con.fill = GridBagConstraints.HORIZONTAL;
		this.add(createMenu(),con);
		
		con.gridx = 0;
		con.gridy = 1;
		con.gridwidth = 2;
		con.weightx = 0;
		con.weighty = 0;
		con.fill = GridBagConstraints.HORIZONTAL;
		this.add(createAnimationToolBar(),con);
		
		con.gridx = 2;
		con.gridy = 1;
		con.gridwidth = 1;
		con.weightx = 0;
		con.fill = GridBagConstraints.HORIZONTAL;
		con.insets = new Insets(0,50,0,0);
		this.add(createObjectsToolBar(),con);
		con.insets = new Insets(0,0,0,0);
		
//		con.gridx = 3;
//		con.gridy = 1;
//		con.gridwidth = 1;
//		con.weightx = 0;
//		con.fill = GridBagConstraints.BOTH;
//		this.add(createViewPointToolBar(),con);
		
		con.gridx = 0;
		con.gridy = 2;
		con.weightx = 0;
		con.weighty = 1;
		con.gridwidth = 1;
		con.fill = GridBagConstraints.VERTICAL;
		con.anchor = GridBagConstraints.LINE_START;
		this.add(createTreePanel(),con);
		
		con.gridx = 1;
		con.gridy = 2;
		con.weightx = 1;
		con.weighty = 1;
		con.gridwidth = 2;
		con.fill = GridBagConstraints.BOTH;
		con.anchor = GridBagConstraints.LINE_START;
		this.add(createOpenGLPanel(),con);
		
		con.gridx = 3;
		con.gridy = 2;
		con.weightx = 0;
		con.weighty = 1;
		con.gridwidth = 1;
		con.fill = GridBagConstraints.VERTICAL;
		con.anchor = GridBagConstraints.LINE_START;
		propertiesPanel = new JPanel();
		propertiesPanel.setLayout(new GridBagLayout());
		contentPanel= new JPanel();
		propertiesPanel.add(contentPanel);
		propertiesPanel.setPreferredSize(new Dimension(350,400));
		this.add(propertiesPanel,con);
		this.pack();
		this.setVisible(true);
		
		listener = new JoglEventListener(canvas);
		listener.setActivModel(new VrmlModel(this));
		canvas.addGLEventListener(listener);
		anim = new Animator(canvas);
		addAnimatorToFrame(this,anim);
		Transformator.setTransformator(this);
		anim.start();
		treePopupMenu = createPopupMenu();
		Main.addWindowOpened();
		this._window=this;
	}
	
	public void setPropertiesPanel(JPanel propPanel){
		GridBagConstraints con = new GridBagConstraints();
		con.gridx = 0;
		con.gridy = 0;
		con.weightx = 1;
		con.weighty = 1;
		con.fill = GridBagConstraints.BOTH;
		con.anchor = GridBagConstraints.LINE_START;
		propertiesPanel.remove(contentPanel);
		propertiesPanel.add(propPanel,con);
		propPanel.setPreferredSize(new Dimension(350,400));
		contentPanel = propPanel;
		propertiesPanel.validate();
		
	}
	
	private JPanel createTreePanel(){
		JPanel treePanel = new JPanel();
		treePanel.setLayout(new BorderLayout());
		treePanel.setBorder(BorderFactory.createBevelBorder(1));
		treePanel.setPreferredSize(new Dimension(300,400));
		
		DefaultMutableTreeNode modelNode = new DefaultMutableTreeNode("Model");
		UserObjectTreeModel treeModel = new UserObjectTreeModel(modelNode);
		modelTree = new JTree(treeModel);
		modelTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
		modelTree.getModel().addTreeModelListener(new RenameTreeModelListener());
		modelTree.addMouseListener(new TreeMouseListener());
		modelTree.setInvokesStopCellEditing(true);
		modelTree.setEditable(true);
		modelTree.setCellEditor(new NonLeafEditor(modelTree, new DefaultTreeCellRenderer()));
		JScrollPane treePane = new JScrollPane(modelTree);
		treePanel.add(treePane,BorderLayout.CENTER);
		return treePanel;
	}
	
	public DefaultMutableTreeNode addNodeToTree(VrmlObject obj){
		DefaultMutableTreeNode root = (DefaultMutableTreeNode)modelTree.getModel().getRoot();
		DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(obj.getName());
		DefaultMutableTreeNode newNodeProperties = new DefaultMutableTreeNode(obj);
		DefaultMutableTreeNode newNodeChildrens = new DefaultMutableTreeNode("Children");
		DefaultMutableTreeNode newNodeShape = new DefaultMutableTreeNode(((VrmlShape)((VrmlTransform)obj).getChildren().getFirst()));
		DefaultMutableTreeNode newNodeShapeGeometry = new DefaultMutableTreeNode("Geometry");
		DefaultMutableTreeNode newNodeShapeGeometryObj = new DefaultMutableTreeNode(((VrmlShape)((VrmlTransform)obj).getChildren().getFirst()).getGeometry());
		DefaultMutableTreeNode newNodeShapeAppearance = new DefaultMutableTreeNode("Appearance");
		DefaultMutableTreeNode newNodeShapeAppearanceObj = new DefaultMutableTreeNode(((VrmlShape)((VrmlTransform)obj).getChildren().getFirst()).getAppearence());
		((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNode, root, root.getChildCount());
		((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodeProperties, newNode, newNode.getChildCount());
		((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodeChildrens, newNode, newNode.getChildCount());
		((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodeShape, newNodeChildrens, newNodeChildrens.getChildCount());
		((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodeShapeAppearance, newNodeShape, newNodeShape.getChildCount());
		((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodeShapeAppearanceObj, newNodeShapeAppearance, newNodeShapeAppearance.getChildCount());
		((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodeShapeGeometry, newNodeShape, newNodeShape.getChildCount());
		((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodeShapeGeometryObj, newNodeShapeGeometry, newNodeShapeGeometry.getChildCount());

		modelTree.expandPath(new TreePath(newNodeShapeAppearance.getPath()));	
		modelTree.expandPath(new TreePath(newNodeShapeGeometry.getPath()));	
		return newNode;
	}

	public void addViewPointNodeToTree(VrmlObject viewPoint){
		DefaultMutableTreeNode root = (DefaultMutableTreeNode)modelTree.getModel().getRoot();
		DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("ViewPoint");
		DefaultMutableTreeNode newNodePosition = new DefaultMutableTreeNode(viewPoint);
		((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNode, root, root.getChildCount());
		((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodePosition, newNode, newNode.getChildCount());
		modelTree.expandPath(new TreePath(newNode.getPath()));	

	}
	
	public DefaultMutableTreeNode addChildTransformationToNode(VrmlObject obj,DefaultMutableTreeNode parent){
		DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(obj.getName());
		DefaultMutableTreeNode newNodeProperties = new DefaultMutableTreeNode(obj);
		if ((parent.isRoot())){
			((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNode, parent, parent.getChildCount());
			((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodeProperties, newNode, newNode.getChildCount());
		}
		else if (parent.getChildCount() < 2){
			DefaultMutableTreeNode newNodeChildrens = new DefaultMutableTreeNode("Children");
			((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodeChildrens, parent, parent.getChildCount());
			((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNode, newNodeChildrens, newNodeChildrens.getChildCount());
			((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodeProperties, newNode, newNode.getChildCount());
		}
		else{
			DefaultMutableTreeNode childArrayNode = (DefaultMutableTreeNode)parent.getChildAt(1);
			((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNode, childArrayNode, childArrayNode.getChildCount());
			((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodeProperties, newNode, newNode.getChildCount());
		}
		modelTree.expandPath(new TreePath(newNode.getPath()));	
		return newNode;
	}
	
	public DefaultMutableTreeNode addNodeAsChildToTree(VrmlObject obj,DefaultMutableTreeNode root){
		if (root.getChildCount() < 2){
			DefaultMutableTreeNode childNode = new DefaultMutableTreeNode("Children");
			((DefaultTreeModel)modelTree.getModel()).insertNodeInto(childNode, root, root.getChildCount());
		}
		root = (DefaultMutableTreeNode)root.getChildAt(1);
		DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(obj.getName());
		DefaultMutableTreeNode newNodeProperties = new DefaultMutableTreeNode(obj);
		DefaultMutableTreeNode newNodeChildrens = new DefaultMutableTreeNode("Children");
		DefaultMutableTreeNode newNodeShape = new DefaultMutableTreeNode(((VrmlTransform)obj).getChildren().getFirst());
		DefaultMutableTreeNode newNodeShapeGeometry = new DefaultMutableTreeNode("Geometry");
		DefaultMutableTreeNode newNodeShapeGeometryObj = new DefaultMutableTreeNode(((VrmlShape)((VrmlTransform)obj).getChildren().getFirst()).getGeometry());
		DefaultMutableTreeNode newNodeShapeAppearance = new DefaultMutableTreeNode("Appearance");
		DefaultMutableTreeNode newNodeShapeAppearanceObj = new DefaultMutableTreeNode(((VrmlShape)((VrmlTransform)obj).getChildren().getFirst()).getAppearence());
		((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNode, root, root.getChildCount());
		((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodeProperties, newNode, newNode.getChildCount());
		((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodeChildrens, newNode, newNode.getChildCount());
		((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodeShape, newNodeChildrens, newNodeChildrens.getChildCount());
		((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodeShapeAppearance, newNodeShape, newNodeShape.getChildCount());
		((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodeShapeAppearanceObj, newNodeShapeAppearance, newNodeShapeAppearance.getChildCount());
		((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodeShapeGeometry, newNodeShape, newNodeShape.getChildCount());
		((DefaultTreeModel)modelTree.getModel()).insertNodeInto(newNodeShapeGeometryObj, newNodeShapeGeometry, newNodeShapeGeometry.getChildCount());

		modelTree.expandPath(new TreePath(newNodeShapeAppearance.getPath()));	
		modelTree.expandPath(new TreePath(newNodeShapeGeometry.getPath()));	
		return newNode;
	}
	
	private JPanel createOpenGLPanel(){
		JPanel openGLPanel = new JPanel();
		openGLPanel.setLayout(new BorderLayout());
    	GLCapabilities capabilities = new GLCapabilities();
    	capabilities.setDoubleBuffered(true);
    	capabilities.setHardwareAccelerated(true);
		canvas = new GLCanvas(capabilities);
		//canvas.addMouseListener(new OpenGlMouseListener(this));
		openGLPanel.add(canvas,BorderLayout.CENTER);
		openGLPanel.setPreferredSize(new Dimension(0,0)); //musi byt inak sa joglovske okno nikdy nezmensi pre resize
		return openGLPanel;
	}
	
	private JMenuBar createMenu(){
		JMenuBar menuBar = new JMenuBar();
		JMenu fileMenu = new JMenu("File");
		fileMenu.setMnemonic(KeyEvent.VK_F);
		JMenu aboutMenu = new JMenu("About");
		aboutMenu.setMnemonic(KeyEvent.VK_A);
		JMenu editMenu = new JMenu("Edit");
		editMenu.setMnemonic(KeyEvent.VK_E);
		JMenu viewMenu = new JMenu("View");
		viewMenu.setMnemonic(KeyEvent.VK_V);
		JMenu windowMenu = new JMenu("Window");
		windowMenu.setMnemonic(KeyEvent.VK_W);
		
		JMenuItem exitItem = new JMenuItem("Exit");
		exitItem.setMnemonic(KeyEvent.VK_E);
		exitItem.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				if (listener.getActivModel().wasModelChanged()){
					   int option = JOptionPane.showConfirmDialog(contentPanel, "There are unsaved changes in model do you wish to save changes?");
					   if (option == JOptionPane.CANCEL_OPTION) return;
					   else if (option == JOptionPane.YES_OPTION){
						   listener.getActivModel().getIoobject().exportToFile();
					   }
					   else if (option == JOptionPane.NO_OPTION){
						   exitWindow();
						   return;
					   }
				   }
				   exitWindow();
			}
		});
		
		JMenuItem newItem = new JMenuItem("New");
		newItem.setMnemonic(KeyEvent.VK_N);
		newItem.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0) {
				new MainFrame();
			}
		});
		
		JMenuItem openItem = new JMenuItem("Open");
		openItem.setMnemonic(KeyEvent.VK_O);
		openItem.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0) {
				if (createNewModel()) listener.getActivModel().getIoobject().importFromFile();
			}
		});
		
		JMenuItem exportItem = new JMenuItem("Save");
		exportItem.setMnemonic(KeyEvent.VK_S);
		exportItem.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0) {
				listener.getActivModel().getIoobject().exportToFile();
				// TODO: zmenit export to file na boolean aby po uspesnom exporte zavolala tato druha metoda zatial sa vola vzdy to je zle
				listener.getActivModel().resetModelChanged();
			}
		});
		fileMenu.add(newItem);
		fileMenu.add(openItem);
		fileMenu.add(exportItem);
		fileMenu.add(exitItem);
		
		JMenuItem addTransformationItem = new JMenuItem("Add transformation");
		addTransformationItem.setMnemonic(KeyEvent.VK_T);
		addTransformationItem.addActionListener(new AddTransformationActionListener());
		JMenuItem addCubeItem = new JMenuItem("Add cube");
		addCubeItem.setMnemonic(KeyEvent.VK_C);
		addCubeItem.addActionListener(new AddCubeActionListener(this));
		JMenuItem addSphereItem = new JMenuItem("Add sphere");
		addSphereItem.setMnemonic(KeyEvent.VK_S);
		addSphereItem.addActionListener(new AddSphereActionListener(this));
		JMenuItem addCylinderItem = new JMenuItem("Add cylinder");
		addCylinderItem.setMnemonic(KeyEvent.VK_L);
		addCylinderItem.addActionListener(new AddCylinderActionListener(this));
		JMenuItem addConeItem = new JMenuItem("Add cone");
		addConeItem.setMnemonic(KeyEvent.VK_N);
		addConeItem.addActionListener(new AddConeActionListener(this));
		JMenuItem addViewpointItem = new JMenuItem("Add viewpoint");
		addViewpointItem.setMnemonic(KeyEvent.VK_V);
		addViewpointItem.addActionListener(new AddViewActionListener(this));
		JMenuItem addBackgroundItem = new JMenuItem("Set background");
		addBackgroundItem.setMnemonic(KeyEvent.VK_B);
		addBackgroundItem.addActionListener(new BackgroundActionListener(this));
		editMenu.add(addTransformationItem);
		editMenu.add(addCubeItem);
		editMenu.add(addSphereItem);
		editMenu.add(addCylinderItem);
		editMenu.add(addConeItem);
		editMenu.add(addViewpointItem);
		editMenu.add(addBackgroundItem);
		
		JMenuItem rotXItem = new JMenuItem("Rotate around X");
		rotXItem.setMnemonic(KeyEvent.VK_X);
		rotXItem.setToolTipText("Rotate scane around X axis.");
		rotXItem.addActionListener(new RotXActionListener());
		JMenuItem rotYItem = new JMenuItem("Rotate around Y");
		rotYItem.setMnemonic(KeyEvent.VK_Y);
		rotYItem.setToolTipText("Rotate scane around Y axis.");
		rotYItem.addActionListener(new RotYActionListener());
		JMenuItem rotZItem = new JMenuItem("Rotate around Z");
		rotZItem.setMnemonic(KeyEvent.VK_Z);
		rotZItem.setToolTipText("Rotate scane around Z axis.");
		rotZItem.addActionListener(new RotZActionListener());
		JMenuItem moveRightItem = new JMenuItem("Move to right");
		moveRightItem.setMnemonic(KeyEvent.VK_R);
		moveRightItem.setToolTipText("Move in x axis direction");
		moveRightItem.addActionListener(new MovRActionListener());
		JMenuItem moveLeftItem = new JMenuItem("Move to left");
		moveLeftItem.setMnemonic(KeyEvent.VK_L);
		moveLeftItem.setToolTipText("Move in x axis direction");
		moveLeftItem.addActionListener(new MovLActionListener());
		JMenuItem moveUpItem = new JMenuItem("Move up");
		moveUpItem.setMnemonic(KeyEvent.VK_U);
		moveUpItem.setToolTipText("Move in y axis direction");
		moveUpItem.addActionListener(new MovUActionListener());
		JMenuItem moveDownItem = new JMenuItem("Move down");
		moveDownItem.setMnemonic(KeyEvent.VK_D);
		moveDownItem.setToolTipText("Move in y axis direction");
		moveDownItem.addActionListener(new MovDActionListener());
		JMenuItem moveFrontItem = new JMenuItem("Move to front");
		moveFrontItem.setMnemonic(KeyEvent.VK_F);
		moveFrontItem.setToolTipText("Move in z axis direction");
		moveFrontItem.addActionListener(new MovFActionListener());
		JMenuItem moveBackItem = new JMenuItem("Move to back");
		moveBackItem.setMnemonic(KeyEvent.VK_B);
		moveBackItem.setToolTipText("Move in z axis direction");
		moveBackItem.addActionListener(new MovBActionListener());	
		viewMenu.add(rotXItem);
		viewMenu.add(rotYItem);
		viewMenu.add(rotZItem);
		viewMenu.add(moveRightItem);
		viewMenu.add(moveLeftItem);
		viewMenu.add(moveUpItem);
		viewMenu.add(moveDownItem);
		viewMenu.add(moveFrontItem);
		viewMenu.add(moveBackItem);
		
		JMenuItem aboutItem = new JMenuItem("About VRML Editor 1.0");
		aboutItem.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0) {
				JOptionPane.showMessageDialog(null, "<html><b>VRML Editor</b> (Team project no.4)<br><b>Current version:</b> 1.0<br><b>Authors:</b> Bucka Peter,Havrila Vlastimil,Svarc Jaroslav<br><b>Team leader:</b> Ing.Michal Blaho<br>2011/2012 FEI ITvR STU Bratislava</html>", "About VRML Editor 1.0", JOptionPane.INFORMATION_MESSAGE, new ImageIcon("images/logoFEI.png"));
			}
		});
		aboutItem.setMnemonic(KeyEvent.VK_A);
		aboutMenu.add(aboutItem);
		
		JMenuItem settingsItem = new JMenuItem("Settings");
		settingsItem.setMnemonic(KeyEvent.VK_S);
		settingsItem.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0) {
				showSettingsDialog();
			}
		});
		windowMenu.add(settingsItem);
		
		menuBar.add(fileMenu);
		menuBar.add(editMenu);
		menuBar.add(viewMenu);
		menuBar.add(windowMenu);
		menuBar.add(aboutMenu);
		menuBar.setMinimumSize(new Dimension(24,20));
		return menuBar;
	}
	
//	private JToolBar createViewPointToolBar(){
//		JToolBar viewToolBar = new JToolBar();
//		viewToolBar.setFloatable(false);
//		ArrayList<String> names=new ArrayList<String>();
//		names.add("default");
//		for (VrmlViewPoint viewpoint : viewpoints) {
//			names.add(viewpoint.getName());
//		}
//		JComboBox viewsComboBox = new JComboBox(names.toArray());
//		viewToolBar.add(viewsComboBox);
//		return viewToolBar;
//	}
	
	private JToolBar createAnimationToolBar(){
		JToolBar animToolBar = new JToolBar();
		animToolBar.setFloatable(false);
		
		JButton newButton = new JButton(new ImageIcon("images/new.png"));
		newButton.setToolTipText("Open new window");
		newButton.setFocusPainted(false);
		newButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0) {
				new MainFrame();
			}
		});
		JButton openButton = new JButton(new ImageIcon("images/openicon.png"));
		openButton.setToolTipText("Open VRML file");
		openButton.setFocusPainted(false);
		openButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0) {
				if (createNewModel()) listener.getActivModel().getIoobject().importFromFile();
			}	
		});
		JButton saveButton = new JButton(new ImageIcon("images/saveicon.png"));
		saveButton.setToolTipText("Save VRML file");
		saveButton.setFocusPainted(false);
		saveButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0) {
				listener.getActivModel().getIoobject().exportToFile();
				// TODO: zmenit export to file na boolean aby po uspesnom exporte zavolala tato druha metoda zatial sa vola vzdy to je zle
				listener.getActivModel().resetModelChanged();
			}	
		});
		JButton rotXButt = new JButton(new ImageIcon("images/xaxis.png"));
		rotXButt.setToolTipText("Rotate scane around X axis.");
		rotXButt.setFocusPainted(false);
		rotXButt.addActionListener(new RotXActionListener());
		JButton rotYButt  = new JButton(new ImageIcon("images/yaxis.png"));
		rotYButt.setToolTipText("Rotate scane around Y axis.");
		rotYButt.setFocusPainted(false);
		rotYButt.addActionListener(new RotYActionListener());
		JButton rotZButt = new JButton(new ImageIcon("images/zaxis.png"));
		rotZButt.setToolTipText("Rotate scane around Z axis.");
		rotZButt.setFocusPainted(false);
		rotZButt.addActionListener(new RotZActionListener());
		JButton moveRight = new JButton(new ImageIcon("images/left.png"));
		moveRight.setToolTipText("Move in x axis direction");
		moveRight.setFocusPainted(false);
		moveRight.addActionListener(new MovRActionListener());
		JButton moveLeft = new JButton(new ImageIcon("images/right.png"));
		moveLeft.setToolTipText("Move in x axis direction");
		moveLeft.setFocusPainted(false);
		moveLeft.addActionListener(new MovLActionListener());
		JButton moveUp = new JButton(new ImageIcon("images/top.png"));
		moveUp.setToolTipText("Move in y axis direction");
		moveUp.setFocusPainted(false);
		moveUp.addActionListener(new MovUActionListener());
		JButton moveDown = new JButton(new ImageIcon("images/bot.png"));
		moveDown.setToolTipText("Move in y axis direction");
		moveDown.setFocusPainted(false);
		moveDown.addActionListener(new MovDActionListener());
		JButton moveFront = new JButton(new ImageIcon("images/back.png"));
		moveFront.setToolTipText("Move in z axis direction");
		moveFront.setFocusPainted(false);
		moveFront.addActionListener(new MovFActionListener());
		JButton moveBack = new JButton(new ImageIcon("images/front.png"));
		moveBack.setToolTipText("Move in z axis direction");
		moveBack.setFocusPainted(false);
		moveBack.addActionListener(new MovBActionListener());
		//animToolBar.add(startAnimButt);
		//animToolBar.add(stopAnimButt);
		animToolBar.add(newButton);
		animToolBar.add(openButton);
		animToolBar.add(saveButton);
		animToolBar.add(rotXButt);
		animToolBar.add(rotYButt);
		animToolBar.add(rotZButt);
		animToolBar.add(moveRight);
		animToolBar.add(moveLeft);
		animToolBar.add(moveUp);
		animToolBar.add(moveDown);
		animToolBar.add(moveFront);
		animToolBar.add(moveBack);
		return animToolBar;
	}
	
	/**
	 * Vytvori toolbar s tlacidlami na pridavanie objektov.
	 * @return
	 */
	private JToolBar createObjectsToolBar(){
		JToolBar objToolBar = new JToolBar();
		objToolBar.setFloatable(false);
		JButton cubeButt = new JButton(new ImageIcon("images/cube.png"));
		cubeButt.setToolTipText("Add cube to scene.");
		cubeButt.setFocusPainted(false);
		cubeButt.setBackground(Color.WHITE);
		cubeButt.addActionListener(new AddCubeActionListener(this));
		JButton sphereButt =  new JButton(new ImageIcon("images/sphere.png"));
		sphereButt.setToolTipText("Add sphere to scene.");
		sphereButt.setFocusPainted(false);
		sphereButt.setBackground(Color.WHITE);
		sphereButt.addActionListener(new AddSphereActionListener(this));
		JButton cylinderButt = new JButton(new ImageIcon("images/cylinder.png"));
		cylinderButt.setToolTipText("Add cylinder to scene.");
		cylinderButt.setFocusPainted(false);
		cylinderButt.setBackground(Color.WHITE);
		cylinderButt.addActionListener(new AddCylinderActionListener(this));
		JButton coneButt = new JButton(new ImageIcon("images/cone.png"));
		coneButt.setToolTipText("Add cone to scene.");
		coneButt.setFocusPainted(false);
		coneButt.setBackground(Color.WHITE);
		coneButt.addActionListener(new AddConeActionListener(this));


		JButton transformButt = new JButton(new ImageIcon("images/transformation.png"));
		transformButt.setToolTipText("Add transformation.");
		transformButt.setFocusPainted(false);
		transformButt.setBackground(Color.WHITE);
		transformButt.addActionListener(new AddTransformationActionListener());
		// Tu je nove tlacidlo pre viewpoint
		JButton viewButt = new JButton(new ImageIcon("images/camera.png"));
		viewButt.setToolTipText("Add viewpoint to scene.");
		viewButt.setFocusPainted(false);
		viewButt.setBackground(Color.WHITE);
		viewButt.addActionListener(new AddViewActionListener(this));
		JButton backgroundButt = new JButton(new ImageIcon("images/background.png"));
		backgroundButt.setToolTipText("Set background properties.");
		backgroundButt.setFocusPainted(false);
		backgroundButt.setBackground(Color.WHITE);
		backgroundButt.addActionListener(new BackgroundActionListener(this));
		
		objToolBar.add(cubeButt);
		objToolBar.add(sphereButt);
		objToolBar.add(cylinderButt);
		objToolBar.add(coneButt);
		objToolBar.add(transformButt);
		objToolBar.add(viewButt);
		objToolBar.add(backgroundButt);
		return objToolBar;
	}
	
	private static void addAnimatorToFrame(JFrame frame,final Animator anim) { 
		frame.addWindowListener(new WindowAdapter() {	
			public void windowClosing(WindowEvent e) {
				anim.stop();
		    }
		});
	 }
	
	/*private class StartAnimActionListener implements ActionListener{
		MainFrame window;
		public StartAnimActionListener(MainFrame w){
			window = w;
		}
		public void actionPerformed(ActionEvent arg0) {
			window.getAnimator().start();
		}	
	}
	
	private class StopAnimActionListener implements ActionListener{
		MainFrame window;
		public StopAnimActionListener(MainFrame w){
			window = w;
		}
		public void actionPerformed(ActionEvent arg0) {
			window.getAnimator().stop();
		}	
	}*/
	
	private class RotXActionListener implements ActionListener{
		public void actionPerformed(ActionEvent arg0) {
			listener.incAngleX();
		}	
	}
	
	private class RotYActionListener implements ActionListener{
		public void actionPerformed(ActionEvent arg0) {
			listener.incAngleY();
		}	
	}
	
	private class RotZActionListener implements ActionListener{
		public void actionPerformed(ActionEvent arg0) {
			listener.incAngleZ();
		}	
	}
	
	private class MovRActionListener implements ActionListener{
		public void actionPerformed(ActionEvent arg0) {
			listener.moveRight();
		}	
	}
	private class MovLActionListener implements ActionListener{
		public void actionPerformed(ActionEvent arg0) {
			listener.moveLeft();
		}	
	}
	private class MovUActionListener implements ActionListener{
		public void actionPerformed(ActionEvent arg0) {
			listener.moveUp();
		}	
	}
	private class MovDActionListener implements ActionListener{
		public void actionPerformed(ActionEvent arg0) {
			listener.moveDown();
		}	
	}
	private class MovFActionListener implements ActionListener{
		public void actionPerformed(ActionEvent arg0) {
			listener.moveFront();
		}	
	}
	private class MovBActionListener implements ActionListener{
		public void actionPerformed(ActionEvent arg0) {
			listener.moveBack();
		}	
	}
	
	private class AddCubeActionListener implements ActionListener{
		MainFrame window;
		public AddCubeActionListener(MainFrame w){
			window = w;
		}
		public void actionPerformed(ActionEvent arg0) {
			VrmlTransform newTransformation;
			newTransformation = new VrmlTransform(new VrmlShape(new VrmlBox((float)2,(float)2,(float)2),new VrmlAppearance()));
			newTransformation.setTranslationX(0);
			newTransformation.setTranslationY(0);
			newTransformation.setTranslationZ(0);
			if (addToHierarchy){
				hierarchyParent.addChild(newTransformation);
				addNodeAsChildToTree(newTransformation,hierarchyNode);
				addToHierarchy = false;
			}
			else listener.getActivModel().addComponentToModel(newTransformation);
		}	
	}
	
	private class AddSphereActionListener implements ActionListener{
		MainFrame window;
		public AddSphereActionListener(MainFrame w){
			window = w;
		}
		public void actionPerformed(ActionEvent arg0) {
			VrmlTransform newTransformation;
			newTransformation = new VrmlTransform(new VrmlShape(new VrmlSphere((float)1.0),new VrmlAppearance()));
			newTransformation.setTranslationX(0);
			newTransformation.setTranslationY(0);
			newTransformation.setTranslationZ(0);
			if (addToHierarchy){
				hierarchyParent.addChild(newTransformation);
				addNodeAsChildToTree(newTransformation,hierarchyNode);
				addToHierarchy = false;
			}
			else listener.getActivModel().addComponentToModel(newTransformation);
		}	
	}
	
	private class AddCylinderActionListener implements ActionListener{
		MainFrame window;
		public AddCylinderActionListener(MainFrame w){
			window = w;
		}
		public void actionPerformed(ActionEvent arg0) {
			VrmlTransform newTransformation;
			newTransformation = new VrmlTransform(new VrmlShape(new VrmlCylinder((float)1,(float)2,true,true,true),new VrmlAppearance()));
			newTransformation.setTranslationX(0);
			newTransformation.setTranslationY(0);
			newTransformation.setTranslationZ(0);
			if (addToHierarchy){
				hierarchyParent.addChild(newTransformation);
				addNodeAsChildToTree(newTransformation,hierarchyNode);
				addToHierarchy = false;
			}
			else listener.getActivModel().addComponentToModel(newTransformation);
		}	
	}
	
	private class AddConeActionListener implements ActionListener{
		MainFrame window;
		public AddConeActionListener(MainFrame w){
			window = w;
		}
		public void actionPerformed(ActionEvent arg0) {
			VrmlTransform newTransformation;
			newTransformation = new VrmlTransform(new VrmlShape(new VrmlCone((float)1,(float)2,true,true),new VrmlAppearance()));
			newTransformation.setTranslationX(0);
			newTransformation.setTranslationY(0);
			newTransformation.setTranslationZ(0);
			if (addToHierarchy){
				hierarchyParent.addChild(newTransformation);
				addNodeAsChildToTree(newTransformation,hierarchyNode);
				addToHierarchy = false;
			}
			else listener.getActivModel().addComponentToModel(newTransformation);
		}	
	}
	
	private class AddTextActionListener implements ActionListener{
		MainFrame window;
		public AddTextActionListener(MainFrame w){
			window = w;
		}
		public void actionPerformed(ActionEvent arg0) {
			VrmlTransform newTransformation;
			String[] str = {"Test string"};
			int[] lenghts = {6};
			newTransformation = new VrmlTransform(new VrmlShape(new VrmlText(str,new SFNode(),lenghts,(float)0.4),new VrmlAppearance()));
			newTransformation.setTranslationX(0);
			newTransformation.setTranslationY(0);
			newTransformation.setTranslationZ(0);
			if (addToHierarchy){
				hierarchyParent.addChild(newTransformation);
				addNodeAsChildToTree(newTransformation,hierarchyNode);
				addToHierarchy = false;
			}
			else listener.getActivModel().addComponentToModel(newTransformation);
		}	
	}

	private class AddViewActionListener implements ActionListener{
		MainFrame window;
		public AddViewActionListener(MainFrame w){
			window = w;
		}
		public void actionPerformed(ActionEvent arg0) {
			VrmlViewPoint viewPoint=new VrmlViewPoint(ViewPointnumber);	
			ArrayList <VrmlViewPoint> viewpoints=viewpointStorage.getViewpoints();
			viewpoints.add(viewPoint);
			ViewPointnumber++;
			listener.getActivModel().addViewPointToModel(viewPoint);
		}	
	}
	
	private class AddTransformationActionListener implements ActionListener{
		public void actionPerformed(ActionEvent arg0) {
			listener.getActivModel().addTransformationToModel(new VrmlTransform(),(DefaultMutableTreeNode)modelTree.getModel().getRoot());
		}	
	}
	
	private class BackgroundActionListener implements ActionListener{
		MainFrame window;
		public BackgroundActionListener(MainFrame w){
			window = w;
		}
		public void actionPerformed(ActionEvent arg0) {
			VrmlBackground background = listener.getActivModel().getModelBackground();
			if (background != null) setPropertiesPanel(new PropertiesWindow(listener.getActivModel().getModelBackground(),listener.getActivModel(), window));
			else setPropertiesPanel(new PropertiesWindow(new VrmlBackground(null,null),listener.getActivModel(), window));
		}	
	}
	/*
	private class OpenGlMouseListener implements MouseListener{
		MainFrame window;
		public OpenGlMouseListener(MainFrame w){
			window = w;
		}
		public void mouseClicked(MouseEvent me) {
			addComponentOfType(window.cursorType,me.getX(),me.getY());
			window.setCursorType(0);
			window.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
		}
		public void mouseEntered(MouseEvent arg0) {}
		public void mouseExited(MouseEvent arg0) {}
		public void mousePressed(MouseEvent arg0) {}
		public void mouseReleased(MouseEvent arg0) {}	
		
		
		//Pridavany objekt je vzdy zabaleny v transformacii
		 
		public void addComponentOfType(int type,int x,int y){
			VrmlTransform newTransformation;
			if (type==Constants.AddCubeCursor){
				newTransformation = new VrmlTransform(new VrmlShape(new VrmlBox((float)2,(float)2,(float)2),new VrmlAppearance()));
				//newTransformation.setTranslationX(Transformator.transformXPositionToCords(x)-(float)listener.getXMove());
				newTransformation.setTranslationX(0);
				newTransformation.setTranslationY(0);
				newTransformation.setTranslationZ(0);
				if (addToHierarchy){
					hierarchyParent.addChild(newTransformation);
					addNodeAsChildToTree(newTransformation,hierarchyNode);
					addToHierarchy = false;
				}
				else listener.getActivModel().addComponentToModel(newTransformation);
				//listener.getActivModel().addComponentToModel(new VrmlBox(100,100,100,Transformator.transformXPositionToCords(x),Transformator.transformYPositionToCords(y),0));
			}else if(type==Constants.AddSphereCursor){
				newTransformation = new VrmlTransform(new VrmlShape(new VrmlSphere((float)1.0),new VrmlAppearance()));
				newTransformation.setTranslationX(0);
				newTransformation.setTranslationY(0);
				newTransformation.setTranslationZ(0);
				if (addToHierarchy){
					hierarchyParent.addChild(newTransformation);
					addNodeAsChildToTree(newTransformation,hierarchyNode);
					addToHierarchy = false;
				}
				else listener.getActivModel().addComponentToModel(newTransformation);
			}else if(type==Constants.AddCylinderCursor){
				newTransformation = new VrmlTransform(new VrmlShape(new VrmlCylinder((float)1,(float)2,true,true,true),new VrmlAppearance()));
				newTransformation.setTranslationX(0);
				newTransformation.setTranslationY(0);
				newTransformation.setTranslationZ(0);
				if (addToHierarchy){
					hierarchyParent.addChild(newTransformation);
					addNodeAsChildToTree(newTransformation,hierarchyNode);
					addToHierarchy = false;
				}
				else listener.getActivModel().addComponentToModel(newTransformation);
			}else if(type==Constants.AddConeCursor){
				newTransformation = new VrmlTransform(new VrmlShape(new VrmlCone((float)1,(float)2,true,true),new VrmlAppearance()));
				newTransformation.setTranslationX(0);
				newTransformation.setTranslationY(0);
				newTransformation.setTranslationZ(0);
				if (addToHierarchy){
					hierarchyParent.addChild(newTransformation);
					addNodeAsChildToTree(newTransformation,hierarchyNode);
					addToHierarchy = false;
				}
				else listener.getActivModel().addComponentToModel(newTransformation);
			}else if(type==Constants.AddTextCursor){
				String[] str = {"Test string"};
				int[] lenghts = {6};
				newTransformation = new VrmlTransform(new VrmlShape(new VrmlText(str,new SFNode(),lenghts,(float)0.4),new VrmlAppearance()));
				newTransformation.setTranslationX(0);
				newTransformation.setTranslationY(0);
				newTransformation.setTranslationZ(0);
				if (addToHierarchy){
					hierarchyParent.addChild(newTransformation);
					addNodeAsChildToTree(newTransformation,hierarchyNode);
					addToHierarchy = false;
				}
				else listener.getActivModel().addComponentToModel(newTransformation);
			}else if(type==Constants.AddViewCursor){//TODO a tu mi to zavola metodu na vytvorenie stromu
				VrmlViewPoint viewPoint=new VrmlViewPoint(ViewPointnumber);	
				ArrayList <VrmlViewPoint> viewpoints=VrmlViewPointsStorage.getViewpoints();
				viewpoints.add(viewPoint);
				ViewPointnumber++;
				listener.getActivModel().addViewPointToModel(viewPoint);
			}
		}
	}*/

	
	private class TreeMouseListener implements MouseListener{
		public void mouseClicked(MouseEvent me) {
			if (me.getClickCount() != 2) return;
			DefaultMutableTreeNode node = (DefaultMutableTreeNode)modelTree.getLastSelectedPathComponent();
			if (node == null) return;
			if (node.isRoot()) return;
			else if (!node.isLeaf()) return;
			else if (node.getUserObject() instanceof String)return;
			else{
				if (_window==null){
					_window=Main.getWindow();
				}
				setPropertiesPanel(new PropertiesWindow(node.getUserObject(),listener.getActivModel(), _window));
			}
			
		}
		public void mouseEntered(MouseEvent arg0) {}
		public void mouseExited(MouseEvent arg0) {}
		public void mousePressed(MouseEvent me) {
			/*if (SwingUtilities.isRightMouseButton(me)) {  
			   int row = modelTree.getClosestRowForLocation(me.getX(), me.getY()); 
			   modelTree.setSelectionRow(row);  
			} */
			evaluatePopup(me);
		}
		public void mouseReleased(MouseEvent me) {
			evaluatePopup(me);
		}
		
		public void evaluatePopup(MouseEvent me){
			int row = modelTree.getClosestRowForLocation(me.getX(), me.getY()); 
			modelTree.setSelectionRow(row);
			if (me.isPopupTrigger()){
				DefaultMutableTreeNode dmtn, node; 
		    	TreePath path = modelTree.getSelectionPath();
		    	dmtn = (DefaultMutableTreeNode) path.getLastPathComponent();
		    	if (dmtn.isLeaf()) return;
		    	if (dmtn.getChildCount() > 2) return;
		    	// celkom zle riesenie ale zatial staci
		    	try{
		    		if (((DefaultMutableTreeNode)dmtn.getChildAt(0)).getUserObject() instanceof VrmlViewPoint){
		    			((JPopupMenu)createViewPointPopupMenu()).show( (JComponent)me.getSource(), me.getX(), me.getY());
		    			return;
		    		}
		    		if (dmtn.getUserObject() instanceof VrmlShape){
		    			((JPopupMenu)createShapePopupMenu()).show( (JComponent)me.getSource(), me.getX(), me.getY());
		    			return;
		    		}
		    		VrmlTransform trans = (VrmlTransform)((DefaultMutableTreeNode)dmtn.getChildAt(0)).getUserObject();
		    	}catch(Exception e){return;}
				treePopupMenu.show( (JComponent)me.getSource(), me.getX(), me.getY());
				return;
			}
		}
		
	}
	
	class RenameTreeModelListener implements TreeModelListener {
		public void treeNodesChanged(TreeModelEvent te) {
			DefaultMutableTreeNode node;  
	        node = (DefaultMutableTreeNode)(te.getTreePath().getLastPathComponent()); 
	        try {  
	              int index = te.getChildIndices()[0]; 
	              node = (DefaultMutableTreeNode)(node.getChildAt(index)); 
	          } catch (NullPointerException exc) {}  
	       if (node.getChildCount() > 0){
	    	   if (((DefaultMutableTreeNode)node.getChildAt(0)).isLeaf()){
	    		   VrmlObject obj = (VrmlObject)((DefaultMutableTreeNode)node.getChildAt(0)).getUserObject();
	    		   obj.setName(node.toString());
	    	   }else if (node.getUserObject() instanceof VrmlShape){	   
	    		  VrmlObject obj = (VrmlObject)node.getUserObject();
	    		  obj.setName(node.toString());
	    	   }
	       }
		}
		public void treeNodesInserted(TreeModelEvent arg0) {}
		public void treeNodesRemoved(TreeModelEvent arg0) {}
		public void treeStructureChanged(TreeModelEvent arg0) {}
	
	}
	
	public Animator getAnimator(){
		 return anim;
	}

	public GLCanvas getCanvas(){
		return canvas;
	}
	
	public void setCursorType(int t){
		this.cursorType = t;
	}
	
	public boolean createNewModel(){
		if (!listener.getActivModel().getModelComponents().isEmpty()){
			int option = JOptionPane.showConfirmDialog(this, "Are you sure you want to open new model? There is existing one still opened in application.","Create new model",JOptionPane.YES_NO_OPTION);
			if (option == JOptionPane.NO_OPTION) return false;
		}
		
		GridBagConstraints con = new GridBagConstraints();
		con.gridx = 0;
		con.gridy = 0;
		con.weightx = 1;
		con.weighty = 1;
		con.fill = GridBagConstraints.BOTH;
		con.anchor = GridBagConstraints.LINE_START;
		propertiesPanel.remove(contentPanel);
		contentPanel = new JPanel();
		propertiesPanel.add(contentPanel,con);
		
		
		listener.setActivModel(new VrmlModel(this));
		DefaultMutableTreeNode modelNode = new DefaultMutableTreeNode("Model");
		modelTree.setModel(new DefaultTreeModel(modelNode));
		return true;
	}
	
	public JPopupMenu createPopupMenu(){
		JPopupMenu popupMenu = new JPopupMenu();
		JMenuItem addTransformItem = new JMenuItem("Add transformation as child");
		addTransformItem.addActionListener(new PopupActionListener());
		JMenuItem addCubeItem = new JMenuItem("Add cube as child");
		addCubeItem.addActionListener(new PopupActionListener());
		JMenuItem addSphereItem = new JMenuItem("Add sphere as child");
		addSphereItem.addActionListener(new PopupActionListener());
		JMenuItem addConeItem = new JMenuItem("Add cone as child");
		addConeItem.addActionListener(new PopupActionListener());
		JMenuItem addCylinderItem = new JMenuItem("Add cylinder as child");
		addCylinderItem.addActionListener(new PopupActionListener());
		JMenuItem removeItem = new JMenuItem("Remove");
		removeItem.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0) {
				 DefaultMutableTreeNode dmtn; 
			     TreePath path = modelTree.getSelectionPath();
			     dmtn = (DefaultMutableTreeNode) path.getLastPathComponent();
			     if (dmtn.getParent() == modelTree.getModel().getRoot()){
			    	 VrmlTransform transformation = (VrmlTransform)((DefaultMutableTreeNode)dmtn.getChildAt(0)).getUserObject();
			     	listener.getActivModel().removeVrmlObject(transformation);
			     }else{
			    	 VrmlTransform transformation = (VrmlTransform)((DefaultMutableTreeNode)dmtn.getParent().getParent().getChildAt(0)).getUserObject();
			    	 transformation.removeChild((VrmlTransform)((DefaultMutableTreeNode)dmtn.getChildAt(0)).getUserObject());
			     }
			     removeNodeFromTree( dmtn);
			}
		});
		
		popupMenu.add(addTransformItem);
		popupMenu.add(addCubeItem);
		popupMenu.add(addSphereItem);
		popupMenu.add(addConeItem);
		popupMenu.add(addCylinderItem);
		popupMenu.add(removeItem);
		popupMenu.setOpaque(true);
		popupMenu.setLightWeightPopupEnabled(true);
		return popupMenu;
	}
	
	public JPopupMenu createShapePopupMenu(){
		JPopupMenu popupMenu = new JPopupMenu();
		JMenuItem removeItem = new JMenuItem("Remove");
		removeItem.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0) {
				 DefaultMutableTreeNode dmtn; 
			     TreePath path = modelTree.getSelectionPath();
			     dmtn = (DefaultMutableTreeNode) path.getLastPathComponent();
			     VrmlTransform transformation = (VrmlTransform)((DefaultMutableTreeNode)dmtn.getParent().getParent().getChildAt(0)).getUserObject();
			     transformation.removeChild((VrmlShape)dmtn.getUserObject());
			     removeNodeFromTree( dmtn);
			}
		});
		popupMenu.add(removeItem);
		popupMenu.setOpaque(true);
		popupMenu.setLightWeightPopupEnabled(true);
		return popupMenu;
	}
	
	public JPopupMenu createViewPointPopupMenu(){
		JPopupMenu popupMenu = new JPopupMenu();
		JMenuItem removeItem = new JMenuItem("Remove");
		removeItem.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0) {
				 DefaultMutableTreeNode dmtn; 
			     TreePath path = modelTree.getSelectionPath();
			     dmtn = (DefaultMutableTreeNode) path.getLastPathComponent();
			     VrmlViewPoint viewPoint = (VrmlViewPoint)((DefaultMutableTreeNode)dmtn.getChildAt(0)).getUserObject();
			     /**
			      * TODO: odstranit viewpoint 
			      */
			     removeNodeFromTree( dmtn);
			}
		});
		popupMenu.add(removeItem);
		popupMenu.setOpaque(true);
		popupMenu.setLightWeightPopupEnabled(true);
		return popupMenu;
	}
	
	class PopupActionListener implements ActionListener{
		public void actionPerformed(ActionEvent e) {
			 addToHierarchy = false; // poistka
			 DefaultMutableTreeNode dmtn; 
		     TreePath path = modelTree.getSelectionPath();
		     dmtn = (DefaultMutableTreeNode) path.getLastPathComponent();
		     VrmlTransform transformation = (VrmlTransform)((DefaultMutableTreeNode)dmtn.getChildAt(0)).getUserObject();
		     if (e.getActionCommand().equals("Add transformation as child")) {
		    	 VrmlTransform newTransformation = new VrmlTransform();
		    	 transformation.addChild(newTransformation);
		    	 addChildTransformationToNode(newTransformation,dmtn);
		     }
		     if (e.getActionCommand().equals("Add cube as child")) {
		    	 addToHierarchy = true;
		    	 hierarchyNode = dmtn;
		    	 hierarchyParent = transformation;
		    	 addCubeMethod();
		     }
		     if (e.getActionCommand().equals("Add sphere as child")) {
		    	 addToHierarchy = true;
		    	 hierarchyNode = dmtn;
		    	 hierarchyParent = transformation;
		    	 addSpehereMethod();
		     }
		     if (e.getActionCommand().equals("Add cone as child")) {
		    	 addToHierarchy = true;
		    	 hierarchyNode = dmtn;
		    	 hierarchyParent = transformation;
		    	 addCylinderMethod();
		     }
		     if (e.getActionCommand().equals("Add cylinder as child")) {
		    	 addToHierarchy = true;
		    	 hierarchyNode = dmtn;
		    	 hierarchyParent = transformation;
		    	 addConeMethod();
		     }
		}
		
	}
	
	public void removeNodeFromTree( DefaultMutableTreeNode dmtn ){
		 ((DefaultTreeModel)modelTree.getModel()).removeNodeFromParent(dmtn);
	}
	
	public JTree getTreeModel(){
		return modelTree;
	}
	
	public void exitWindow(){
		Main.decWindowOpened();
		if (Main.getNumOfWindows() == 0){
			anim.stop();
			System.exit(0);
		}else{
			anim.stop();
			this.dispose();
		}
	}
	
	private void addSpehereMethod(){	
			VrmlTransform newTransformation;
			newTransformation = new VrmlTransform(new VrmlShape(new VrmlSphere((float)1.0),new VrmlAppearance()));
			newTransformation.setTranslationX(0);
			newTransformation.setTranslationY(0);
			newTransformation.setTranslationZ(0);
			if (addToHierarchy){
				hierarchyParent.addChild(newTransformation);
				addNodeAsChildToTree(newTransformation,hierarchyNode);
				addToHierarchy = false;
			}
			else listener.getActivModel().addComponentToModel(newTransformation);
	}
	
	private void addCubeMethod(){
			VrmlTransform newTransformation;
			newTransformation = new VrmlTransform(new VrmlShape(new VrmlBox((float)2,(float)2,(float)2),new VrmlAppearance()));
			newTransformation.setTranslationX(0);
			newTransformation.setTranslationY(0);
			newTransformation.setTranslationZ(0);
			if (addToHierarchy){
				hierarchyParent.addChild(newTransformation);
				addNodeAsChildToTree(newTransformation,hierarchyNode);
				addToHierarchy = false;
			}
			else listener.getActivModel().addComponentToModel(newTransformation);	
	}
	
	private void addCylinderMethod(){
		VrmlTransform newTransformation;
		newTransformation = new VrmlTransform(new VrmlShape(new VrmlCylinder((float)1,(float)2,true,true,true),new VrmlAppearance()));
		newTransformation.setTranslationX(0);
		newTransformation.setTranslationY(0);
		newTransformation.setTranslationZ(0);
		if (addToHierarchy){
			hierarchyParent.addChild(newTransformation);
			addNodeAsChildToTree(newTransformation,hierarchyNode);
			addToHierarchy = false;
		}
		else listener.getActivModel().addComponentToModel(newTransformation);
	}	
	
	private void addConeMethod() {
		VrmlTransform newTransformation;
		newTransformation = new VrmlTransform(new VrmlShape(new VrmlCone((float)1,(float)2,true,true),new VrmlAppearance()));
		newTransformation.setTranslationX(0);
		newTransformation.setTranslationY(0);
		newTransformation.setTranslationZ(0);
		if (addToHierarchy){
			hierarchyParent.addChild(newTransformation);
			addNodeAsChildToTree(newTransformation,hierarchyNode);
			addToHierarchy = false;
		}
		else listener.getActivModel().addComponentToModel(newTransformation);
	}
	
	public void showSettingsDialog(){
		final JDialog settingsDialog = new JDialog();
		settingsDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
		settingsDialog.setTitle("Settings");
		settingsDialog.setLayout(new FlowLayout());
		settingsDialog.setPreferredSize(new Dimension(370,170));
		settingsDialog.setResizable(false);
		
		JLabel angleLabel = new JLabel("Rotation step angle:");
		final JTextField angleField = new JTextField(Integer.toString(listener.getRotSize()));
		angleField.setPreferredSize(new Dimension(30,30));
		angleField.setEditable(false);
		JSlider angle = new JSlider(JSlider.HORIZONTAL,1, 45, 10);
		angle.setMajorTickSpacing(10);
		angle.setMinorTickSpacing(1);
		angle.setPaintTicks(true);
		angle.setPaintLabels(true);
		angle.addChangeListener(new SliderListener(angleField));
		
		JLabel stepLabel = new JLabel("Movement step size:");
		final JTextField stepField = new JTextField(Integer.toString(listener.getMoveSize()));
		stepField.setEditable(false);
		stepField.setPreferredSize(new Dimension(30,30));
		JSlider step = new JSlider(JSlider.HORIZONTAL,1, 5, 1);
		step.setMajorTickSpacing(4);
		step.setMinorTickSpacing(1);
		step.setPaintTicks(true);
		step.setPaintLabels(true);
		step.addChangeListener(new SliderListener(stepField));
		
		settingsDialog.add(angleLabel);
		settingsDialog.add(angleField);
		settingsDialog.add(angle);
		
		settingsDialog.add(stepLabel);
		settingsDialog.add(stepField);
		settingsDialog.add(step);
		
		JButton applyButton = new JButton("Apply");
		applyButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0) {
				listener.setRotSize(Integer.valueOf(angleField.getText()));
				listener.setMoveSize(Integer.valueOf(stepField.getText()));
				settingsDialog.dispose();
			}
		});
		settingsDialog.add(applyButton);
		
		settingsDialog.pack();
		settingsDialog.setVisible(true);
	}
	
	class SliderListener implements ChangeListener {
		private JTextField field;
		public SliderListener(JTextField f){
			field = f;
		}
	    public void stateChanged(ChangeEvent e) {
	        JSlider source = (JSlider)e.getSource();
	        if (!source.getValueIsAdjusting()) {
	        	field.setText(Integer.toString((int)source.getValue()));
	        }    
	    }
	}
	
	class UserObjectTreeModel extends DefaultTreeModel{
		public UserObjectTreeModel(TreeNode root){
			super(root);
		}
		
		public void valueForPathChanged(TreePath path, Object newValue){
			DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
			if (node.getUserObject() instanceof VrmlShape){
				((VrmlShape)node.getUserObject()).setName(newValue.toString());
			}else{
				node.setUserObject(newValue);
			}
		    nodeChanged(node);
		}
	}

	

}
